#include "test_async_dns.h"
#include "cm_uart.h"
#include "cm_demo_uart.h"
//#include "cm_etimer.h"
#include "assert.h"
#include "cm_async_dns.h"

//static cm_etimer_manager_t test_etimer_manager = {NULL};
static cm_eloop_handle_t dns_eloop = NULL;
static int addr_type;
static void test_async_dns_event(int req_id, cm_async_dns_event_e event, void *cb_param,
                                  const char *host_name, const cm_async_dns_ip_addr_t *ip_addr)
{
    cm_demo_printf("__on_async_dns_event(%d, %d, %s,%s)\n", req_id, event, host_name,cb_param);

    switch (event)
    {
    case CM_ASYNC_DNS_RESOLVE_OK: {
        char ip_str[128] = "";
        if (CM_ASYNC_DNS_ADDRTYPE_IPV4 == ip_addr->type)
        {
            inet_ntop(AF_INET, &(ip_addr->u_addr.sin_addr), ip_str, sizeof(ip_str));
        }
        else if (CM_ASYNC_DNS_ADDRTYPE_IPV6 == ip_addr->type)
        {
            inet_ntop(AF_INET6, &(ip_addr->u_addr.sin6_addr), ip_str, sizeof(ip_str));
        }
        cm_demo_printf("dns req(%d) ok: %s->%s\n", req_id, host_name, ip_str);
        break;
    }
    case CM_ASYNC_DNS_RESOLVE_FAIL:
        cm_demo_printf("dns req(%d) fail: %s\n", req_id, host_name);
        break;
    default:
        break;
    }
}

/* eloop执行线程 */
static void adns_eloop_thread_proc(void *argument)
{
    cm_log_printf(0, "__eloop_thread_proc\n");
    /* 启动事件循环 */
    while (1)
    {
        //uint32_t wait_time = cm_etimer_get_wait_time(&test_etimer_manager);
        //cm_demo_printf("wait time:%u\n",wait_time);
        //int ret = cm_eloop_wait_event(dns_eloop, wait_time);
        int ret = cm_eloop_wait_event(dns_eloop, CM_ELOOP_WAIT_FOREVER);
        if (ret < 0)
        {
            break;
        }
        //cm_etimer_run(&test_etimer_manager);
    }

    /* 删除事件循环 */
    cm_eloop_delete(dns_eloop);
    osThreadExit();
}
/* 执行环境为eloop线程(和异步socket在同一个线程,可以安全地处理socket创建和数据收发等操作) */
static void cm_test_eloop_cmd_DNS_recv_event(cm_eloop_event_handle_t event, void *cb_param)
{
    /* 注销Event */
    cm_eloop_unregister_event(event);

    /* 取得参数 */
    char *host_name = (char *)cb_param;

    cm_demo_printf("__on_eloop_cmd_DNS_recv_event host_name=%s\n", host_name);

    /* 处理命令 */
    cm_async_dns_ip_addr_t ip_addr;
    cm_demo_printf("addr_type %d\n",addr_type);
    int ret = cm_async_dns_request(host_name, addr_type, &ip_addr, test_async_dns_event, "DNS_CB");
    OCTEST_FUNC_EXPECT_GREATER_OR_EQUAL_INT32(0,ret,cm_async_dns_request);
    if (0 == ret)
    {
        char ip_str[128] = "";
        if (CM_ASYNC_DNS_ADDRTYPE_IPV4 == ip_addr.type)
        {
            inet_ntop(AF_INET, &(ip_addr.u_addr.sin_addr), ip_str, sizeof(ip_str));
        }
        else if (CM_ASYNC_DNS_ADDRTYPE_IPV6 == ip_addr.type)
        {
            inet_ntop(AF_INET6, &(ip_addr.u_addr.sin6_addr), ip_str, sizeof(ip_str));
        }
        cm_demo_printf("dns req ok: %s->%s\n", host_name, ip_str);
    }
    else if (ret > 0)
    {
        cm_demo_printf("dns req(%d) pending...\n", ret);
    }
    else
    {
        cm_demo_printf("dns req fail %d\n", ret);
    }

    free(host_name);
}

/* 被平台AT引擎调用, 执行环境为平台AT线程 */
static void cm_test_cmd_DNS(void *param)
{
    /* 处理参数 */
    char *host_name = strdup(((char **)param)[0]);
    assert(NULL != host_name);

    cm_demo_printf("__on_cmd_DNS host_name=%s\n", host_name);

    /* 注册Event(将命令封装成Event发送到eloop执行) */
    cm_eloop_event_handle_t cmd_DNS_recv_event = cm_eloop_register_event(dns_eloop, cm_test_eloop_cmd_DNS_recv_event, (void *)host_name);
    /* 发送到eloop执行 */
    cm_eloop_post_event(cmd_DNS_recv_event);
}

static osThreadId_t test_async_dns_thread_handle =NULL;

void cm_test_async_dns_operation(unsigned char*cmd[],int len)
{
    if(0 == strncmp("INIT",cmd[2],strlen("INIT")))
    {
        //cm_eloop_init();
        //cm_etimer_manager_init(&test_etimer_manager);
        // dns_eloop = cm_eloop_create(10);
        // if (NULL == dns_eloop)
        // {
        //     cm_demo_printf("creat eloop fail!\n");
        //     return;
        // }
        // cm_demo_printf("dns eloop:%p\n",dns_eloop);
        //cm_demo_printf("cm_async_dns_init ret:%d\n",cm_async_dns_init(4, dns_eloop));
        /* 创建eloop执行线程 */
        if(NULL == test_async_dns_thread_handle)
        {
            dns_eloop = cm_eloop_create(10);
            if (NULL == dns_eloop)
            {
                cm_demo_printf("creat eloop fail!\n");
                return;
            }
            cm_demo_printf("dns eloop:%p\n",dns_eloop);
            osThreadAttr_t thread_attr = {0};
            thread_attr.name = "test_eloop";
            thread_attr.stack_size = 2048;
            test_async_dns_thread_handle = osThreadNew(adns_eloop_thread_proc, NULL, &thread_attr);
        }
    }else if(0 == strncmp("GET_ELOOP",cmd[2],strlen("GET_ELOOP")))
    {
        cm_eloop_handle_t async_dns_eloop = NULL;
        async_dns_eloop = cm_async_dns_eloop();
        cm_demo_printf("cm_async_dns_eloop ret:%p\n",async_dns_eloop);
        OCTEST_FUNC_EXPECT_NOT_NULL(async_dns_eloop,cm_async_dns_eloop);
    }else if(0 == strncmp("SET_PRIORITY",cmd[2],strlen("SET_PRIORITY")))
    {
        uint8_t priority = atoi(cmd[3]);
        int32_t dns_set_priority_ret = cm_async_dns_set_priority(priority);
        cm_demo_printf("cm_async_dns_set_priority ret:%d\n",dns_set_priority_ret);
        OCTEST_FUNC_EXPECT_EQUAL_INT32(0,dns_set_priority_ret,cm_async_dns_set_priority);
    
    }else if(0 == strncmp("REQUEST",cmd[2],strlen("REQUEST")))
    {
        const char *host_name = cmd[3];
        cm_async_dns_ip_addr_t ip_addr;
        if(0 == strcmp("IPV4",cmd[4]))
        {
            addr_type = CM_ASYNC_DNS_ADDRTYPE_IPV4;
        }else if(0 == strcmp("IPV6",cmd[4]))
        {
            addr_type = CM_ASYNC_DNS_ADDRTYPE_IPV6;
        }else if(0 == strcmp("IPV4V6",cmd[4]))
        {
            addr_type = CM_ASYNC_DNS_ADDRTYPE_IPV4_IPV6;
        }else if(0 == strcmp("IPV6V4",cmd[4]))
        {
            addr_type = CM_ASYNC_DNS_ADDRTYPE_IPV6_IPV4;
        }
        else{
            cm_demo_printf("param error!\n");
        }
        //cm_demo_printf("cm_async_dns_request ret:%d\n",cm_async_dns_request(host_name,addr_type,
        //                 &ip_addr, test_async_dns_event, "dns request"));
        cm_test_cmd_DNS(cmd+3);
    }
    else{
        cm_demo_printf("param error!\n");
    }
}